package com.yserp.project.erp.store.inorder.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yserp.common.exception.BusinessException;
import com.yserp.common.utils.DateUtils;
import com.yserp.common.utils.StringUtils;
import com.yserp.common.utils.bean.BeanUtils;
import com.yserp.common.utils.mybatis.MybatisPlusUtil;
import com.yserp.common.utils.security.ShiroUtils;
import com.yserp.common.utils.text.Convert;
import com.yserp.project.erp.common.enums.CheckStatusEnums;
import com.yserp.project.erp.common.enums.DeliverStatusEnums;
import com.yserp.project.erp.common.enums.InOrderTypeEnums;
import com.yserp.project.erp.common.enums.OrderEnums;
import com.yserp.project.erp.common.util.DateSearchUtils;
import com.yserp.project.erp.order.productorder.domain.ProductionOrder;
import com.yserp.project.erp.order.productorder.domain.ProductionOrderItem;
import com.yserp.project.erp.order.productorder.domain.ProductionOrderVo;
import com.yserp.project.erp.order.productorder.service.IProductionOrderItemService;
import com.yserp.project.erp.order.productorder.service.IProductionOrderService;
import com.yserp.project.erp.order.purchorder.domain.PurchOrder;
import com.yserp.project.erp.order.purchorder.domain.PurchOrderItem;
import com.yserp.project.erp.order.purchorder.domain.PurchOrderVo;
import com.yserp.project.erp.order.purchorder.service.IPurchOrderItemService;
import com.yserp.project.erp.order.purchorder.service.IPurchOrderService;
import com.yserp.project.erp.record.checkorderlog.domain.CheckOrderLog;
import com.yserp.project.erp.record.checkorderlog.service.ICheckOrderLogService;
import com.yserp.project.erp.store.inorder.domain.InOrder;
import com.yserp.project.erp.store.inorder.domain.InOrderDto;
import com.yserp.project.erp.store.inorder.domain.InOrderItem;
import com.yserp.project.erp.store.inorder.domain.InOrderVo;
import com.yserp.project.erp.store.inorder.mapper.InOrderMapper;
import com.yserp.project.erp.store.inorder.service.IInOrderItemService;
import com.yserp.project.erp.store.inorder.service.IInOrderService;
import com.yserp.project.erp.store.instorelog.domain.StockInLog;
import com.yserp.project.erp.store.stock.domain.Stock;
import com.yserp.project.erp.store.stock.service.IStockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 商品入库单主Service业务层处理
 *
 * @author yserp
 * @date 2022-07-01
 */
@Service
public class InOrderServiceImpl extends ServiceImpl<InOrderMapper, InOrder> implements IInOrderService {
    @Resource
    private InOrderMapper inOrderMapper;
    @Autowired
    private IInOrderItemService inOrderItemService;
    @Autowired
    private ICheckOrderLogService checkOrderLogService;
    @Autowired
    private IStockService stockService;
    @Autowired
    private IPurchOrderService purchOrderService;
    @Autowired
    private IPurchOrderItemService purchOrderItemService;
    @Autowired
    private IProductionOrderService productionOrderService;
    @Autowired
    private IProductionOrderItemService productionOrderItemService;

    /**
     * 查询商品入库单主
     *
     * @param id 商品入库单主主键
     * @return 商品入库单主
     */
    @Override
    public InOrderVo selectInOrderById(Long id) {
        InOrderVo inOrderVo = new InOrderVo();
        inOrderVo.setInOrder(inOrderMapper.selectById(id));
        inOrderVo.setItems(inOrderItemService.selectInOrderItemByMainId(id));
        return inOrderVo;
    }

    /**
     * 查询商品入库单主列表
     *
     * @param inOrder 商品入库单主
     * @return 商品入库单主
     */
    @Override
    public List<InOrder> selectInOrderList(InOrder inOrder) {
        QueryWrapper<InOrder> query = new QueryWrapper<>();
        MybatisPlusUtil.notNullField(inOrder,query);
        //对时间区间的处理
        DateSearchUtils.queryDateRange(inOrder,query);
        return inOrderMapper.selectList(query);
    }

    @Override
    public String getOrderNo(String orderNo) {
        String cacheOrderNo = OrderEnums.getCacheOrderNo(OrderEnums.IN_ORDER.getPref());
        //单号一致，可从数据库中从新递增
        if(orderNo.equals(cacheOrderNo)){
            Integer count = inOrderMapper.selectCount(new QueryWrapper<InOrder>().eq("order_code", orderNo));
            OrderEnums.putCacheOrderNo(orderNo);
        }

        return cacheOrderNo;
    }

    /**
     * 新增商品入库单主
     *
     * @param inOrderDto 商品入库单主
     * @return 结果
     */
    @Override
    @Transactional
    public int insertInOrder(InOrderDto inOrderDto) {

        List<InOrderItem> items = inOrderDto.getItems();
        if(CollectionUtils.isEmpty(items)){
            throw new BusinessException("子表不能为空");
        }
        //验证单号是否存在
        String orderNo = inOrderDto.getOrderCode();
        if(StringUtils.isBlank(orderNo)){
            throw new BusinessException("单号不存在");
        }
        Integer count = inOrderMapper.selectCount(new QueryWrapper<InOrder>().eq("order_code", orderNo));
        if(count>0){
            //处理单号，并重新插入缓存
            Integer number = inOrderMapper.selectCount(new QueryWrapper<InOrder>().like("order_code", orderNo.substring(0,orderNo.length()-3)));
            OrderEnums.putCacheOrderNo(orderNo,number);
            throw new BusinessException("单号已存在，请刷新单号，再次提交");
        }else{
            OrderEnums.putCacheOrderNo(orderNo);
        }
        //插入主表
        InOrder inOrder = new InOrder();
        BeanUtils.copyBeanProp(inOrder, inOrderDto);
        int i = inOrderMapper.insert(inOrder);
        //批量插入子表
        items.stream().forEach(item->item.setInOrderId(inOrder.getId()));
        boolean flag = inOrderItemService.saveBatch(items);
        if(i>0 && flag){
            i=1;
        }
        return i;
    }

    /**
     * 修改商品入库单主
     *
     * @param inOrderDto 商品入库单主
     * @return 结果
     */
    @Override
    @Transactional
    public int updateInOrder(InOrderDto inOrderDto) {

        List<InOrderItem> items = inOrderDto.getItems();
        if(CollectionUtils.isEmpty(items)){
            throw new BusinessException("子表不能为空");
        }
        //插入主表
        InOrder inOrder = new InOrder();
        BeanUtils.copyBeanProp(inOrder, inOrderDto);
        int i = inOrderMapper.updateById(inOrder);
        //子表
        List<InOrderItem> inOrderItems = inOrderItemService.selectInOrderItemByMainId(inOrder.getId());
        if(!CollectionUtils.isEmpty(inOrderItems)) {
            List<Long> oldIds = inOrderItems.stream().map(InOrderItem::getId).collect(Collectors.toList());
            List<Long> newIds = items.stream().map(InOrderItem::getId).collect(Collectors.toList());
            oldIds.removeAll(newIds);
            if (!CollectionUtils.isEmpty(oldIds)) {
                //批量删除数据
                inOrderItemService.removeByIds(oldIds);
            }
        }

        //插入新加的数据，以及更新数据
        for (InOrderItem item : items) {
            if(null == item.getId()){
                item.setInOrderId(inOrder.getId());
            }
            inOrderItemService.saveOrUpdate(item);

        }
        return i;
    }

    /**
     * 批量删除商品入库单主
     *
     * @param ids 需要删除的商品入库单主主键
     * @return 结果
     */
    @Override
    public int deleteInOrderByIds(String ids) {
        int result = 0;
        Long[] mainIds = Convert.toLongArray(ids);
        for (Long id : mainIds ) {
            result =deleteInOrderById(id);
            if(result <= 0){
                break;
            }
        }
        return result;
    }

    /**
     * 删除商品入库单主信息
     *
     * @param id 商品入库单主主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteInOrderById(Long id) {
        int result = 0;
        //更新主表
        int i= inOrderMapper.deleteById(id);
        //更新子表
        List<InOrderItem> inOrderItems = inOrderItemService.selectInOrderItemByMainId(id);
        if(!CollectionUtils.isEmpty(inOrderItems)) {
            List<Long> itemIds = inOrderItems.stream().map(InOrderItem::getId).collect(Collectors.toList());
            boolean flag = inOrderItemService.removeByIds(itemIds);
            if (i > 0 && flag) {
                result = 1;
            }
        }
        return result;
    }

    @Override
    @Transactional
    public int checkStatus(CheckOrderLog checkOrderLog) {
        int result = 0;
        Long id = checkOrderLog.getId();
        //String status = CheckStatusEnums.OK_CHECK.getCode();
        String orderStatus = checkOrderLog.getOrderStatus();
        //获取入库数据
        InOrder inOrder = inOrderMapper.selectById(id);
        if(CheckStatusEnums.OK_CHECK.getCode().equals(inOrder.getStatus())){
            throw new BusinessException("已审核，无须重复审核");
        }

        //添加审核信息
        CheckOrderLog log = new CheckOrderLog();
        log.setOrderType(OrderEnums.IN_ORDER.getCode());
        log.setOrdeId(id);
        log.setOrderCode(inOrder.getOrderCode());
        log.setOrderStatus(orderStatus);
        log.setAdvice("审核");
        log.setCreateBy(ShiroUtils.getLoginName());
        int i = checkOrderLogService.insertCheckOrderLog(log);
        //更新数据
        InOrder upSetInOrder = new InOrder();
        upSetInOrder.setId(id);
        upSetInOrder.setStatus(orderStatus);
        int j = inOrderMapper.updateById(upSetInOrder);
        if(!CheckStatusEnums.OK_CHECK.getCode().equals(orderStatus)){
            //驳回状态，直接返回
            return 1;
        }
        //回填上游单据
        String orderType = inOrder.getOrderType();
        Long sourceOrderId = inOrder.getSourceOrderId();

        //添加库存信息
        BigDecimal total=BigDecimal.ZERO;
        List<InOrderItem> inOrderItems = inOrderItemService.selectInOrderItemByMainId(id);
        if(!CollectionUtils.isEmpty(inOrderItems)){
            StockInLog stockInLog = null;
            Stock stock = null;
            for (InOrderItem inOrderItem : inOrderItems) {
                //实际入库数量
                BigDecimal actualNumber = inOrderItem.getActualNumber();
                //统计总数量
                total=total.add(actualNumber);
                //采购单
                if(InOrderTypeEnums.PURCH.getCode().equals(orderType) && null != sourceOrderId){
                    PurchOrderItem item = new PurchOrderItem();
                    item.setMainId(sourceOrderId);
                    item.setGoodsId(inOrderItem.getGoodsId());
                    List<PurchOrderItem> items = purchOrderItemService.selectPurchOrderItemList(item);
                    if(!CollectionUtils.isEmpty(items)){
                        PurchOrderItem purchOrderItem = items.get(0);
                        PurchOrderItem updateItem = new PurchOrderItem();
                        updateItem.setId(purchOrderItem.getId());
                        BigDecimal inNumber = purchOrderItem.getInNumber()==null?BigDecimal.ZERO:purchOrderItem.getInNumber();
                        BigDecimal inNums =actualNumber.add(inNumber);
                        updateItem.setInNumber(inNums);
                        purchOrderItemService.updateById(updateItem);
                    }
                }
                //生产单,不作处理
                Date nowDate = DateUtils.getNowDate();
                //库存日志
                stockInLog = new StockInLog();
                stockInLog.setBatchNo(inOrderItem.getBatchNo());
                stockInLog.setInType(inOrder.getOrderType());
                stockInLog.setOrderId(id);
                stockInLog.setOrderCode(inOrder.getOrderCode());
                stockInLog.setGoodId(inOrderItem.getId());
                stockInLog.setGoodCode(inOrderItem.getGoodsCode());
                stockInLog.setGoodName(inOrderItem.getGoodsName());
                stockInLog.setGoodUnit(inOrderItem.getGoodsUnit());
                stockInLog.setGoodUnitDesc(inOrderItem.getGoodsUnitDesc());
                stockInLog.setPackageUnit(inOrderItem.getPackageUnit());
                stockInLog.setPackageNumber(inOrderItem.getPackageNumber());
                stockInLog.setWarehouseId(inOrder.getWarehouseId());
                stockInLog.setWarehouseName(inOrder.getWarehouseName());
                stockInLog.setReservoirId(inOrder.getReservoirId());
                stockInLog.setReservoirName(inOrder.getReservoirName());
                stockInLog.setInNum(actualNumber);
                stockInLog.setInTime(nowDate);
                stockInLog.setCreateBy(ShiroUtils.getLoginName());
                stockInLog.setCreateTime(nowDate);
                //库存
                stock = new Stock();
                stock.setGoodsId(inOrderItem.getGoodsId());
                stock.setGoodsCode(inOrderItem.getGoodsCode());
                stock.setGoodsName(inOrderItem.getGoodsName());
                stock.setGoodsUnit(inOrderItem.getGoodsUnit());
                stock.setGoodsUnitDesc(inOrderItem.getGoodsUnitDesc());
                stock.setStockNumber(actualNumber);
                stock.setBatchNo(inOrderItem.getBatchNo());
                stock.setWarehouseId(inOrder.getWarehouseId());
                stock.setWarehouseName(inOrder.getWarehouseName());
                stock.setReservoirId(inOrder.getReservoirId());
                stock.setReservoirName(inOrder.getReservoirName());
                stockService.inStock(stock,stockInLog);
            }
        }
        //回填主表
        //采购单
        if(InOrderTypeEnums.PURCH.getCode().equals(orderType) && null != sourceOrderId){
            PurchOrder purchOrder = purchOrderService.getById(sourceOrderId);
            purchOrder.setDeliveryStatus(DeliverStatusEnums.OK_IN.getCode());
            BigDecimal inNums = purchOrder.getInNums().add(total);
            purchOrder.setInNums(inNums);
            purchOrderService.updateById(purchOrder);
        }
        //生产单
        if(InOrderTypeEnums.PRODUCT.getCode().equals(orderType) && null != sourceOrderId){
            ProductionOrder productionOrder = productionOrderService.getById(sourceOrderId);
            productionOrder.setDeliveryStatus(DeliverStatusEnums.OK_IN.getCode());
            BigDecimal inNums = productionOrder.getInNum().add(total);
            productionOrder.setInNum(inNums);
            productionOrderService.updateById(productionOrder);
        }
        if(i>0 && j>0){
            result =1;
        }
        return result;

    }

    @Override
    public InOrderVo purchTransfor(Long id) {
        //查询数据
        PurchOrderVo purchOrderVo = purchOrderService.selectPurchOrderById(id);
        PurchOrder purchOrder = purchOrderVo.getPurchOrder();
        List<PurchOrderItem> items = purchOrderVo.getItems();
        //主表
        InOrder inOrder = new InOrder();
        inOrder.setOrderDate(new Date());
        inOrder.setOrderType(InOrderTypeEnums.PURCH.getCode());
        inOrder.setSourceOrderId(purchOrder.getId());
        inOrder.setSourceOrderNo(purchOrder.getOrderNo());
        inOrder.setSupplierId(purchOrder.getSupplierId());
        inOrder.setSupplierName(purchOrder.getSupplierName());
        inOrder.setWarehouseId(purchOrder.getWarehouseId());
        inOrder.setWarehouseName(purchOrder.getWarehouseName());
        //子表
        List<InOrderItem> inOrderItems = new ArrayList<>();
        for (PurchOrderItem item : items) {
            InOrderItem inOrderItem = new InOrderItem();
            inOrderItem.setBatchNo(item.getBatchNo());
            inOrderItem.setGoodsId(item.getGoodsId());
            inOrderItem.setGoodsCode(item.getGoodsCode());
            inOrderItem.setGoodsName(item.getGoodsName());
            inOrderItem.setGoodsUnit(item.getGoodsUnit());
            inOrderItem.setGoodsUnitDesc(item.getGoodsUnitDesc());
            inOrderItem.setPlanNumber(item.getPlanNumber());
            inOrderItem.setRemark("");
            inOrderItems.add(inOrderItem);
        }


        return InOrderVo.builder().inOrder(inOrder).items(inOrderItems).build();
    }

    @Override
    public InOrderVo productTransfor(Long id) {
        //查询数据
        ProductionOrderVo vo = productionOrderService.selectProductionOrderById(id);
        ProductionOrder productionOrder = vo.getProductionOrder();
        List<ProductionOrderItem> items = vo.getItems();
        //主表
        InOrder inOrder = new InOrder();
        inOrder.setOrderDate(new Date());
        inOrder.setOrderType(InOrderTypeEnums.PRODUCT.getCode());
        inOrder.setSourceOrderId(productionOrder.getId());
        inOrder.setSourceOrderNo(productionOrder.getOrderNo());
        //子表
        List<InOrderItem> inOrderItems = new ArrayList<>();
        InOrderItem inOrderItem = new InOrderItem();
        inOrderItem.setBatchNo(productionOrder.getBatchNo());
        inOrderItem.setGoodsId(productionOrder.getGoodsId());
        inOrderItem.setGoodsCode(productionOrder.getGoodsCode());
        inOrderItem.setGoodsName(productionOrder.getGoodsName());
        inOrderItem.setGoodsUnit(productionOrder.getGoodsUnit());
        inOrderItem.setGoodsUnitDesc(productionOrder.getGoodsUnitDesc());
        inOrderItem.setPlanNumber(productionOrder.getGoodsNum());
        inOrderItem.setRemark("");
        inOrderItems.add(inOrderItem);

        return InOrderVo.builder().inOrder(inOrder).items(inOrderItems).build();
    }


}
